﻿using System.Collections.Concurrent;
using System.Threading;

namespace System.Dns.Toolkit.DnsServer {

    public class FirstPriorityQueue<TV> : IPriorityQueue<int, TV> {

        private readonly ConcurrentQueue<TV> _queues = new ConcurrentQueue<TV>();
        private readonly ConcurrentQueue<TV>[] _priorities;

        private int _count;
        
        public FirstPriorityQueue(int priorities) {
            _count = 0;
            _priorities = new ConcurrentQueue<TV>[priorities];
            for (int i = 0; i < priorities; i++) {
                _priorities[i] = new ConcurrentQueue<TV>();   
            }
        }

        public void Enqueue(int priority, TV value) {
            _priorities[priority].Enqueue(value);
            Interlocked.Increment(ref _count);
        }

        public bool TryDequeue(out TV value) {
            if (_queues.TryDequeue(out value)) {
                Interlocked.Decrement(ref _count);
                return true;
            }

            TV v;
            foreach (var q in _priorities) {
                while(q.TryDequeue(out v)) {
                    _queues.Enqueue(v);
                }
            }
            if (_queues.TryDequeue(out value)) {
                Interlocked.Decrement(ref _count);
                return true;
            }
            return false;
        }

        public bool IsEmpty {
            get {
                return _count <= 0;
            }
        }

        public int Count {
            get {
                return _count;
            }
        }

    }


}
